#include "SkyBoxRenderFeature.h"
#include <SERender/Resourses/Loader/VertexArrayLoader.h>
#include <SECore/Manager.h>
#include <SERender/Resourses/Shader.h>
#include <SERender/Renderer/Renderer.h>

namespace SEngine
{
    SkyBoxRenderFeature::SkyBoxRenderFeature(Renderer &renderer)
        : RenderFeature(renderer) 
    {
        InitSkyBoxDrawable();
    }

    void SkyBoxRenderFeature::DrawSkyBox(Texture & cubeTex)
    {
        auto material = Manager::GetInstance().Get<Material>("SkyboxCube").value();
        DrawSkyBox(cubeTex, material);
    }
    
    void SkyBoxRenderFeature::DrawSkyBox(TextureHDR & cubeTex)
    {
        auto material = Manager::GetInstance().Get<Material>("Skybox").value();
        DrawSkyBox(cubeTex, material);
    }


    void SkyBoxRenderFeature::DrawSkyBox(Texture & cubeTex, ResRef<Material> material)
    {
        auto & pso = material.Value().GetPSO();
        pso.blend = false;
        pso.depth = false;
        m_skyBox.SetMaterial(material);
        m_skyBox.GetMaterial().Value().Set("u_irradianceMap", Shader::Sampler{cubeTex, TextureSlot::TEXTURE0});
        m_renderer.DrawEntity(m_skyBox);
    }

    void SkyBoxRenderFeature::DrawSkyBox(TextureHDR &cubeTex, ResRef<Material> material)
    {
        auto & pso = material.Value().GetPSO();
        pso.blend = false;
        pso.depth = false;
        m_skyBox.SetMaterial(material);
        m_skyBox.GetMaterial().Value().Set("u_irradianceMap", Shader::Sampler{cubeTex, TextureSlot::TEXTURE0});
        m_renderer.DrawEntity(m_skyBox);
    }

    void SkyBoxRenderFeature::DrawSkyBox(DynamicSkybox &skybox)
    {
        skybox.Draw(m_renderer);
    }

    void SEngine::SkyBoxRenderFeature::InitSkyBoxDrawable()
    {
        VertexArrayLoader<3> loader(std::make_unique<CurrentDrive>());
        // positions          
        loader.PushVertex({-1.0f,  1.0f, -1.0f});
        loader.PushVertex({-1.0f, -1.0f, -1.0f});
        loader.PushVertex({1.0f, -1.0f, -1.0f});
        loader.PushVertex({1.0f, -1.0f, -1.0f});
        loader.PushVertex({1.0f,  1.0f, -1.0f});
        loader.PushVertex({-1.0f,  1.0f, -1.0f});

        loader.PushVertex({-1.0f, -1.0f,  1.0f});
        loader.PushVertex({-1.0f, -1.0f, -1.0f});
        loader.PushVertex({-1.0f,  1.0f, -1.0f});
        loader.PushVertex({-1.0f,  1.0f, -1.0f});
        loader.PushVertex({-1.0f,  1.0f,  1.0f});
        loader.PushVertex({-1.0f, -1.0f,  1.0f});

        loader.PushVertex({1.0f, -1.0f, -1.0f});
        loader.PushVertex({1.0f, -1.0f,  1.0f});
        loader.PushVertex({1.0f,  1.0f,  1.0f});
        loader.PushVertex({1.0f,  1.0f,  1.0f});
        loader.PushVertex({1.0f,  1.0f, -1.0f});
        loader.PushVertex({1.0f, -1.0f, -1.0f});

        loader.PushVertex({-1.0f, -1.0f,  1.0f});
        loader.PushVertex({-1.0f,  1.0f,  1.0f});
        loader.PushVertex({1.0f,  1.0f,  1.0f});
        loader.PushVertex({1.0f,  1.0f,  1.0f});
        loader.PushVertex({1.0f, -1.0f,  1.0f});
        loader.PushVertex({-1.0f, -1.0f,  1.0f});

        loader.PushVertex({-1.0f,  1.0f, -1.0f});
        loader.PushVertex({1.0f,  1.0f, -1.0f});
        loader.PushVertex({1.0f,  1.0f,  1.0f});
        loader.PushVertex({1.0f,  1.0f,  1.0f});
        loader.PushVertex({-1.0f,  1.0f,  1.0f});
        loader.PushVertex({-1.0f,  1.0f, -1.0f});

        loader.PushVertex({-1.0f, -1.0f, -1.0f});
        loader.PushVertex({-1.0f, -1.0f,  1.0f});
        loader.PushVertex({1.0f, -1.0f, -1.0f});
        loader.PushVertex({1.0f, -1.0f, -1.0f});
        loader.PushVertex({-1.0f, -1.0f,  1.0f});
        loader.PushVertex({1.0f, -1.0f,  1.0f});

        m_skyBox.SetMesh(std::make_unique<Mesh>(loader.CreateVertexArray()));
        m_skyBox.SetAPIType(DrawAPIType::DrawArrays);
        m_skyBox.SetMode(ElemMode::TRIANGLES);
    }

} // namespace SkyBoxRenderFeature
